#!/usr/bin/perl -wc

package RFCMail::ESMTP::Grammar::Parser;

use strict;
use base qw(Exporter);
use Carp;
use RFCMail::ESMTP::Grammar::Base
    qw(QUOTED_STRING_RE
       STRING_RE
       REVERSE_PATH_RE
       FORWARD_PATH_RE
       PATH_RE
       A_D_L_RE
       MAILBOX_RE
       LOCAL_PART_RE
       DOMAIN_RE
       PARAMETERS_RE
       ESMTP_PARAM_RE
       ESMTP_KEYWORD_RE
       ESMTP_VALUE_RE);

our @EXPORT =
    qw(
       decode_quoted_string
       decode_quoted_string_nsc
       decode_string
       decode_string_nsc
       reverse_path_is_null
       reverse_path_is_null_nsc
       forward_path_is_postmaster
       forward_path_is_postmaster_nsc
       split_path
       split_path_nsc
       split_mailbox
       split_mailbox_nsc
       split_adl
       split_adl_nsc
       split_parameters
       split_parameters_nsc
       split_esmtp_param
       split_esmtp_param_nsc
      );


sub syntax_error {
    croak("Argument to ", (caller(1))[3], "() is not of the required type");
}


sub decode_quoted_string_nsc {
    my ($string) = $_[0] =~ /\A"(.*)"\z/;
    $string =~ s/\\(.)/$1/g;
    return ($string);
}


sub decode_quoted_string {
    &syntax_error if $_[0] !~ /\A@{[QUOTED_STRING_RE]}\z/o;
    return (&decode_quoted_string_nsc);
}


sub decode_string_nsc {
    return ($_[0])
	if $_[0] !~ /\A"/;
    return (&decode_quoted_string_nsc);
}


sub decode_string {
    &syntax_error if $_[0] !~ /\A@{[STRING_RE]}\z/o;
    return (&decode_string_nsc);
}


sub reverse_path_is_null_nsc {
    return ($_[0] =~ /\A<>\z/);
}


sub reverse_path_is_null {
    &syntax_error if $_[0] !~ /\A@{[REVERSE_PATH_RE]}\z/o;
    return (&reverse_path_is_null_nsc);
}


sub forward_path_is_postmaster_nsc {
    return ($_[0] =~ /\A<postmaster>\z/i);
}


sub forward_path_is_postmaster {
    &syntax_error if $_[0] !~ /\A@{[FORWARD_PATH_RE]}\z/o;
    return (&forward_path_is_postmaster_nsc);
}


sub split_path_nsc {
    my ($adl, $mailbox) = $_[0] =~ /\A<(?:(@{[A_D_L_RE]}):)?(@{[MAILBOX_RE]})>\z/o;
    return (wantarray ? ($mailbox, $adl) : $mailbox);
}


sub split_path {
    &syntax_error if $_[0] !~ /\A@{[PATH_RE]}\z/o;
    return (&split_path_nsc);
}


sub split_mailbox_nsc {
    return ($_[0] =~ /\A(@{[LOCAL_PART_RE]})\@(@{[DOMAIN_RE]})\z/o);
}


sub split_mailbox {
    croak (__PACKAGE__."::split_mailbox() not defined in scalar context")
	if not wantarray;
    &syntax_error if $_[0] !~ /\A@{[MAILBOX_RE]}\z/o;
    return (&split_mailbox_nsc);
}


sub split_adl_nsc {
    return (map { substr($_, 1) } split(/,/, $_[0]));
}


sub split_adl {
    &syntax_error if $_[0] !~ /\A@{[A_D_L_RE]}\z/o;
    return (&split_adl_nsc);
}


sub split_parameters_nsc {
    return (split(/ /, $_[0]));
}


sub split_parameters {
    &syntax_error if $_[0] !~ /\A@{[PARAMETERS_RE]}\z/o;
    return (&split_parameters_nsc);
}


sub split_esmtp_param_nsc {
    return ($_[0] =~ /\A(@{[ESMTP_KEYWORD_RE]})(?:=(@{[ESMTP_VALUE_RE]}))?\z/o);
}


sub split_esmtp_param {
    &syntax_error if $_[0] !~ /\A@{[ESMTP_PARAM_RE]}\z/o;
    return (&split_esmtp_param_nsc);
}


1;
